package workflowminer.load;

import java.util.Enumeration;
import java.util.List;
import java.util.Vector;

import workflowminer.domain.Role;
import workflowminer.interfaces.AuditTrailEntry;
import workflowminer.interfaces.ProcessInstance;

public class ClusterAlgorithm {
	
	List<ProcessInstance> instances;
	Vector<String> users;
	Vector<Role> initRoles;
	Vector<Role> genRoles = new Vector<Role>();

	public ClusterAlgorithm(Vector<String> users, List<ProcessInstance> inst){
		this.instances=inst;
		this.users = users;
		this.initRoles = new Vector<Role>();
		this.genRoles = new Vector<Role>();
	}
	
	/**
	 * P(u)
	 * @param usuario
	 * @return
	 */
	public Vector<String> getPermission(final String user){
		Vector<String> tasks = new Vector<String>();
		for (ProcessInstance instance : instances) {
			for (AuditTrailEntry entry :  instance.getAuditTrailEntry()){
				if(entry.getOriginator().equals(user) && !tasks.contains(entry.getWorkflowModelElement())){
					tasks.add(entry.getWorkflowModelElement());
				}
			}
		}
		return tasks;
	}
	
	/**
	 * Clustering algorithm
	 * @return
	 */
	public Vector<Role> generateRolesFastMiner(){
		for (String user : users) {
			Role role = new Role(getPermission(user));
			if(!initRoles.contains(role)){
				initRoles.add(role);
			}
			role.setCount(role.getCount()+1);
		}
		for (Role role : initRoles) {
			Vector<String> permissions = role.getPermissions();
			System.out.print("Role: ");
			for (String string : permissions) {
				System.out.print(" "+string);
			}
			System.out.println(" .");
		}
		System.out.println(" .--------------");
		Vector<Role> intersections = new Vector<Role>();
		Role newRole;
		for(Enumeration e1=initRoles.elements();e1.hasMoreElements();)
		{
			Role role=(Role)e1.nextElement();
			initRoles.remove(role);
			for(Enumeration e2=initRoles.elements();e2.hasMoreElements();)
			{
				Role role2=(Role)e2.nextElement();
				newRole = role.getInterseccion(role2);
				intersections.add(newRole);
				if (!newRole.getPermissions().isEmpty()){
					if (!containsSameRole(genRoles,newRole)){
						newRole.setCount(role.getCount()+role2.getCount());
						newRole.addContributor(role2);
						newRole.addContributor(role2);
						genRoles.remove(role);
						genRoles.remove(role2);
						genRoles.add(newRole);
					}
					else {
						if(!newRole.isContributor(role)) {
							newRole.setCount(newRole.getCount()+role.getCount());
							newRole.addContributor(role);
						}
						if(!newRole.isContributor(role2)) {
							newRole.setCount(newRole.getCount()+role2.getCount());
							newRole.addContributor(role2);
						}
					}
				}
			}
			Role rest = this.getRestOfRole(role,intersections);
			if (!rest.getPermissions().isEmpty()) {
				genRoles.add(rest);
			}
			intersections.clear();
		}
		for (Role role : genRoles) {
			Vector<String> permissions = role.getPermissions();
			System.out.print("Role: ");
			for (String string : permissions) {
				System.out.print(" "+string);
			}
			System.out.println("("+role.getCount()+") .");
		}
		return genRoles;
	}

	private boolean containsSameRole(Vector<Role> genRoles2, Role newRole) {
		for (Role role : genRoles2) {
			if (role.getPermissions().equals(newRole.getPermissions())){
				return true;
			}
		}
		return false;
	}

	private Role getRestOfRole(Role role, Vector<Role> intersections) {
		Vector<String> oldPermissions = role.getPermissions();
		for (Role otherRole : intersections) {
			for(String permission : otherRole.getPermissions()){
				oldPermissions.remove(permission);
			}
		}
		Role newRole = new Role(oldPermissions);
		newRole.setCount(role.getCount());
		return newRole;
	}

}
